package com.hhs.storage.config.jwt;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.hhs.storage.bean.BaseUser;
import com.hhs.storage.bean.ResponseInfo;
import com.hhs.storage.service.BaseUserService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import io.jsonwebtoken.Claims;

/*
 * 用于JWT认证的过滤器，启动类要使用注解 @ServletComponentScan
 */
@WebFilter(filterName = "jwtAuthorizeFilter",urlPatterns = {"/*"})
@Slf4j
public class JwtAuthorizeFilter implements Filter{

    @Autowired
    private JwtProperty jwtProperty;

    @Override
    public void destroy() {
    }

    @Resource
    BaseUserService baseUserService;

    @SneakyThrows
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest  httpRequest = (HttpServletRequest)request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With,Token");
        httpResponse.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
        //跨域先要发一个预检请求，再继续执行
        if("OPTIONS".equals(httpRequest.getMethod())) {
            chain.doFilter(httpRequest, httpResponse);
            return;
        }
        String url = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());
        if (isInclude(url)){
            //如果是属于排除的URL，比如登录，注册，验证码等URL，则直接通行
            chain.doFilter(httpRequest, httpResponse);
            return;
        }
        //以下为token验证
        Enumeration<String> list = httpRequest.getHeaderNames();
        String auth = httpRequest.getHeader("token");
        if ((auth != null) && (auth.length() > 7)) {
            String HeadStr = auth.substring(0, 6).toLowerCase();
            if (HeadStr.compareTo("bearer") == 0) {
                auth = auth.substring(7);
                Claims claims = JwtHelper.parseJWT(auth, jwtProperty.getBase64Secret());
                if (claims != null) {
                    //若要对同一用户重复颁发的token做处理，就需要数据库保存token
//                      //获取一下客户端传过来的关键的身份id
//                      String userId = request.getParameter("userId");
                    String jwtUserId = (String) claims.get("userId");
                    BaseUser baseUser = baseUserService.getById(jwtUserId);
                    if(baseUser.getStatus()){
                        if(StringUtils.isNotEmpty(jwtUserId)) {
                            Map<String, String[]> parameterMap = request.getParameterMap();
                            Method method = parameterMap.getClass().getMethod("setLocked",
                                    new Class[]{boolean.class});
                            //打开锁
                            method.invoke(parameterMap, new Object[]{new Boolean(false)});
                            //目前就初始化菜单有用到该数据
                            //BaseMenuController--init
                            parameterMap.put("lgUserId", new String[]{jwtUserId});
                            //关锁
                            method.invoke(parameterMap, new Object[]{new Boolean(true)});
                        }
                        chain.doFilter(request, response);
                        return;
                    }
                }
            }
        }

        //验证不通过
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json; charset=utf-8");
        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        httpResponse.getWriter().write(JSON.toJSONString(ResponseInfo.error("鉴权失败")));
        return;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());
    }

    /**
     * 是否需要过滤
     * @param url
     * @return
     */
    private boolean isInclude(String url) {
        for (String patternUrl : jwtProperty.getExcludeUrl()) {
            Pattern p = Pattern.compile(patternUrl);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }
        return false;
    }
}

